#include "Col.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "DictHashTab.h"
#include "Class.h"

//---- DictHashTab -----------------------------------------------------

NewMetaImpl(DictHashTab,HashTable, (T(capacity)
		/*TVP(keys,capacity), TVP(vals,capacity)*/));

DictHashTab::DictHashTab(int initCapacity, pEqualFunc eq, pHashFunc hsh,
				int *sz) : HashTable(initCapacity, eq, hsh, sz)
{
	tab= new Assoc[capacity + 1];
}

DictHashTab::~DictHashTab()
{
	SafeDelete(tab);
}

void DictHashTab::Empty(int newCapacity)
{
	SafeDelete(tab);

	CalcBounds(newCapacity);
	tab= new Assoc[capacity + 1];
		
	*size= 0;

	Changed();
}

void *DictHashTab::AddAt(void *value, void *key, bool replace)
{
	int slot;
	void *replaced;

	if (SearchFirst(key, slot)) {
		if (replace) {
			replaced= ValueAt(slot);
			SetValueAt(value, slot);
			Changed();
			return replaced;
		}
		return value;
	} else {
		SetKeyAt(key, slot);
		SetValueAt(value, slot);
		(*size)++;
		if (*size >= highWatermark)
			Rehash(NewCapacity(TRUE));
		Changed();
		return 0;
	}
}

void *DictHashTab::AtKey(void *key, EqualType eq)
{
	int slot;

	if (eq ? SearchFirst(key, slot) : SearchPtr(key, slot))
		return ValueAt(slot);
	return 0;
}

void *DictHashTab::FindKey(void *key, void **value, EqualType eq)
{
	int slot;

	key= eq ? SearchFirst(key, slot) : SearchPtr(key, slot);
	if (key)
		*value= ValueAt(slot);
	else
		*value= 0;
	return key;
}

void *DictHashTab::RemoveKey(void *key, void **value, EqualType eq)
{
	int slot;

	key= eq ? SearchFirst(key, slot) : SearchPtr(key, slot);
	if (key) {
		if (value)
			*value= ValueAt(slot);
		RemoveSlot(slot);
		Changed();
	}
	return key;
}

//---- primitives ----

void *DictHashTab::KeyAt(int i)
{
	return tab[i].key;
}

void DictHashTab::SetKeyAt(void *key, int i)
{
	tab[i].key= (Object*) key;
}

void *DictHashTab::ValueAt(int i)
{
	return tab[i].val;
}

void DictHashTab::SetValueAt(void *value, int i)
{
	tab[i].val= (Object*) value;
}

void DictHashTab::NullAt(int i)
{
	tab[i].key= 0;
	tab[i].val= 0;
}

void DictHashTab::Swap(int i, int j)
{
	Assoc t= tab[i];
	tab[i]= tab[j];
	tab[j]= t;
}

void DictHashTab::DoRehash(HashTable *ht)
{
	register int i;
	register DictHashTab *dt= (DictHashTab*) ht;
	for (i= 0; i < capacity; i++)
		if (tab[i].key)
			dt->AddAt(tab[i].val, tab[i].key, FALSE);
}

HashTable *DictHashTab::MakeNew(int initCapacity)
{
	return new DictHashTab(initCapacity, equal, hash);
}

void DictHashTab::Assign(HashTable *ht)
{
	DictHashTab *dht= (DictHashTab*) ht;

	HashTable::Assign(ht);
	SafeDelete(tab);
	tab= dht->tab;
	dht->tab= 0;
}

